package cn.green.utils;

import cn.green.core.annos.column.QColumn;
import cn.green.core.annos.reles.OneToMany;
import cn.green.core.annos.reles.OneToOne;
import cn.green.mvc.entity.OrmTableEntity;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.aspectj.weaver.ast.Or;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;

/**
 * @author wang.yishu
 * @version 1.0
 * @className EntityUtils
 * @description 实体工具组件 废弃
 * @date 2025/7/4 15:16
 */
@Deprecated
public class EntityUtils {

    public static <T extends OrmTableEntity> JSONObject entityToDataJson(T e) {
        if (e == null) {
            return new JSONObject();
        }
        Class<? extends OrmTableEntity> tClass = e.getClass();
        Field[] fields = tClass.getDeclaredFields();
        JSONObject rtn = new JSONObject();
        for (Field field : fields) {
            Map<String, Object> normalData = null;
            try {
                normalData = getNormalData(e, field);
                rtn.putAll(normalData);
            } catch (IllegalAccessException ignored) {
            }

            Map<String, Object> oneToOneData = null;
            try {
                oneToOneData = getOneToOneData(e, field);
                rtn.putAll(oneToOneData);
            } catch (IllegalAccessException ignored) {
            }

            Map<String, Object> oneToManyData = null;
            try {
                oneToManyData = getOneToManyData(e, field);
                rtn.putAll(oneToManyData);
            } catch (IllegalAccessException ignored) {
            }
        }
        rtn.putAll(getOtherData(e));
        return rtn;
    }

    private static <T extends OrmTableEntity> Map<String, Object> getNormalData(T e, Field field) throws IllegalAccessException {
        QColumn column = field.getDeclaredAnnotation(QColumn.class);
        if (column == null) {
            return new HashMap<>();
        }
        Map<String, Object> normalData = new HashMap<>();
        field.setAccessible(true);
        Object o = field.get(e);
        String name = column.name();
        normalData.put(name, o);
        return normalData;
    }

    private static <T extends OrmTableEntity> Map<String, Object> getOneToOneData(T e, Field field) throws IllegalAccessException {
        OneToOne oneToOne = field.getDeclaredAnnotation(OneToOne.class);
        if (oneToOne == null) {
            return new HashMap<>();
        }
        Map<String, Object> oneToOneData = new HashMap<>();
        field.setAccessible(true);
        Object oneToOneValue = field.get(e);
        if (oneToOneValue != null) {
            if (oneToOneValue instanceof OrmTableEntity) {
                JSONObject oneToOneJson = entityToDataJson((OrmTableEntity) oneToOneValue);
                oneToOneData.put(field.getName(), oneToOneJson);
            } else {
                oneToOneData.put(field.getName(), oneToOneValue);
            }
        }
        return oneToOneData;
    }

    private static <T extends OrmTableEntity> Map<String, Object> getOneToManyData(T e, Field field) throws IllegalAccessException {
        OneToMany oneToMany = field.getDeclaredAnnotation(OneToMany.class);
        if (oneToMany == null) {
            return new HashMap<>();
        }
        Map<String, Object> oneToManyData = new HashMap<>();
        field.setAccessible(true);
        Object oneToManyValue = field.get(e);
        if (oneToManyValue != null) {
            JSONArray array = new JSONArray();
            if (oneToManyValue instanceof JSONArray) {
                if (!((JSONArray) oneToManyValue).isEmpty()) {
                    for (int i = 0; i < ((JSONArray) oneToManyValue).size(); i++) {
                        Object item = ((JSONArray) oneToManyValue).get(i);
                        if (item instanceof OrmTableEntity) {
                            array.add(entityToDataJson((OrmTableEntity) item));
                        }
                    }

                }
            } else if (oneToManyValue instanceof Set) {
                if (!((Set<?>) oneToManyValue).isEmpty()) {
                    ((Set<?>) oneToManyValue).forEach(item -> {
                        if (item instanceof OrmTableEntity) {
                            array.add(entityToDataJson((OrmTableEntity) item));
                        }
                    });
                }
            } else if (oneToManyValue instanceof List) {
                if (!((List<?>) oneToManyValue).isEmpty()) {
                    for (Object item : (List<?>) oneToManyValue) {
                        if (item instanceof OrmTableEntity) {
                            array.add(entityToDataJson((OrmTableEntity) item));
                        }
                    }
                }
            }
            oneToManyData.put(field.getName(), array);
        }
        return oneToManyData;
    }

    private static <T extends OrmTableEntity> Map<String, Object> getOtherData(T e) {
        Map<String, Object> rtn = new HashMap<>();
        JSONObject data = e.getData();
        if (data != null) {
            return new HashMap<>(data);
        }
        return rtn;
    }

    public static <T extends OrmTableEntity> T dataJsonToEntity(JSONObject dataJson, Class<T> entityClass) {
        T ins = null;
        try {
            ins = entityClass.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            return null;
        }
        if (dataJson == null) {
            return null;
        }
        Field[] fields = entityClass.getDeclaredFields();
        Set<String> otherColumns = new HashSet<>();
        for (Field field : fields) {
            //开始设置普通属性
            try {
                List<String> excludes = setNormalField(entityClass, field, ins, dataJson);
                if (excludes != null) {
                    otherColumns.addAll(excludes);
                }
            } catch (IllegalAccessException | NoSuchFieldException ignored) {
            }
            //设置一对一属性
            try {
                List<String> excludes = setOneToOneField(entityClass, field, ins, dataJson);
                if (excludes != null) {
                    otherColumns.addAll(excludes);
                }
            } catch (IllegalAccessException | NoSuchFieldException ignored) {
            }
            //设置一对多属性
            try {
                List<String> excludes = setOneToManyField(entityClass, field, ins, dataJson);
                if (excludes != null) {
                    otherColumns.addAll(excludes);
                }
            } catch (IllegalAccessException | NoSuchFieldException ignored) {
            }
        }
        if (!otherColumns.isEmpty()) {
            JSONObject data = new JSONObject();
            dataJson.keySet().forEach(key -> {
                if (!otherColumns.contains(key)) {
                    data.put(key, dataJson.get(key));
                }
            });
            ins.setData(data);
        }
        return ins;
    }

    private static <T extends OrmTableEntity> List<String> setNormalField(Class<T> entityClass, Field field, Object entity, JSONObject dataJson)
            throws IllegalAccessException, NoSuchFieldException {
        QColumn column = field.getAnnotation(QColumn.class);
        if (column == null) {
            return null;
        }
        String columnName = column.name();
        Object columnValue = dataJson.get(columnName);
        if (columnValue != null) {
            set(field, entity, columnValue);
        }
//        String viewFieldName = column.viewFieldName();
//        String viewColumnSuf = column.viewColumnSuf();
//        if (viewFieldName != null && !viewFieldName.isEmpty()) {
//            Field viewField = entityClass.getDeclaredField(viewFieldName);
//            viewField.setAccessible(true);
//            if (viewColumnSuf == null || viewColumnSuf.isEmpty()) {
//                viewField.set(entity, columnValue);
//            } else {
//                Object viewColumnValue = dataJson.get(columnName + viewColumnSuf);
//                if (viewColumnValue != null) {
//                    viewField.set(entity, viewColumnValue);
//                }
//            }
//        }
        return new ArrayList<>(Arrays.asList(field.getName(), column.name()));
    }

    public static void set(Field field, Object entity, Object columnValue) throws IllegalAccessException {
        field.setAccessible(true);
        Class<?> type = field.getType();
        if (type == String.class) {
            field.set(entity, String.valueOf(columnValue));
        } else if (type == Integer.class || type == int.class) {
            field.set(entity, Integer.valueOf(String.valueOf(columnValue)));
        } else if (type == Long.class || type == long.class) {
            field.set(entity, Long.valueOf(String.valueOf(columnValue)));
        } else if (type == Double.class || type == double.class) {
            field.set(entity, Double.valueOf(String.valueOf(columnValue)));
        } else if (type == Float.class || type == float.class) {
            field.set(entity, Float.valueOf(String.valueOf(columnValue)));
        } else if (type == Boolean.class || type == boolean.class) {
            field.set(entity, Boolean.valueOf(String.valueOf(columnValue)));
        } else if (type == Byte.class || type == byte.class) {
            field.set(entity, Byte.valueOf(String.valueOf(columnValue)));
        } else if (type == Short.class || type == short.class) {
            field.set(entity, Short.valueOf(String.valueOf(columnValue)));
        } else if (type == Character.class || type == char.class) {
            field.set(entity, String.valueOf(columnValue).charAt(0));
        }
    }

    private static <T extends OrmTableEntity> List<String> setOneToOneField(Class<T> entityClass, Field field, Object entity, JSONObject dataJson)
            throws IllegalAccessException, NoSuchFieldException {
        OneToOne oneToOne = field.getAnnotation(OneToOne.class);
        if (oneToOne == null) {
            return null;
        }
        Class<?> oneToOneType = field.getType();
        String name = field.getName();
        if (dataJson != null && dataJson.containsKey(name) && OrmTableEntity.class.isAssignableFrom(oneToOneType)) {
            JSONObject oneToOneValue = dataJson.getJSONObject(name);
            if (oneToOneValue != null) {
                OrmTableEntity ormTableEntity = dataJsonToEntity(oneToOneValue, (Class<? extends OrmTableEntity>) oneToOneType);
                if (ormTableEntity != null) {
                    field.setAccessible(true);
                    field.set(entity, ormTableEntity);
                }
            }
        }
        return Collections.singletonList(field.getName());
    }

    private static <T extends OrmTableEntity> List<String> setOneToManyField(Class<T> entityClass, Field field, Object entity, JSONObject dataJson)
            throws IllegalAccessException, NoSuchFieldException{
        OneToMany oneToMany = field.getAnnotation(OneToMany.class);
        if (oneToMany == null) {
            return null;
        }
        Class<?> target = oneToMany.target();
        Class<?> type = field.getType();
        if (Collection.class.isAssignableFrom(type) && dataJson.containsKey(field.getName()) && OrmTableEntity.class.isAssignableFrom(target)) {
            JSONArray oneToManyValues = dataJson.getJSONArray(field.getName());
            String collectionType = "";
            if (oneToManyValues != null && !oneToManyValues.isEmpty()) {
                Object collection = null;
                if (List.class.isAssignableFrom(type)) {
                    collection = new ArrayList<>();
                    collectionType = "List";
                } else if (Set.class.isAssignableFrom(type)) {
                    collection = new HashSet<>();
                    collectionType = "Set";
                } else if (JSONArray.class.isAssignableFrom(type)) {
                    collection = new JSONArray();
                    collectionType = "JSONArray";
                }
                for (int i = 0; i < oneToManyValues.size(); i++) {
                    JSONObject oneToManyValue = oneToManyValues.getJSONObject(i);
                    if (oneToManyValue != null) {
                        OrmTableEntity ormTableEntity = dataJsonToEntity(oneToManyValue, (Class<? extends OrmTableEntity>) target);
                        switch (collectionType) {
                            case "List":
                                ((List<OrmTableEntity>) collection).add(ormTableEntity);
                                break;
                            case "Set":
                                ((Set<OrmTableEntity>) collection).add(ormTableEntity);
                                break;
                            case "JSONArray":
                                ((JSONArray) collection).add(ormTableEntity);
                                break;
                        }
                    }
                }
                field.setAccessible(true);
                field.set(entity, collection);
            }
        }
        return Collections.singletonList(field.getName());
    }
}
